﻿/**
 * @file		dd_pmc_uart.c
 * @brief		uart driver
 * @note		None
 * @attention	None
 * 
 * <B><I>Copyright 2016 Socionext Inc.</I></B>
 */

#include <string.h>
#include "pmc.h"
#include "dd_pmc_uart.h"
#include "dd_pmc_hdmac.h"
#include "dd_pmc_crg.h"
#include "dd_arm.h"

/*----------------------------------------------------------------------*/
/* Definition															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
#define dd_pmc_uart_dsb() Dd_ARM_Dsb_Pou()

// Bit Location
#define D_DD_PMC_UART_SSR_REC_BIT			(1 << 7)				/**< Bit Location of REC on SSR */
#define D_DD_PMC_UART_DR_D8_BIT				(1 << 8)				/**< Bit Location of D8 on DR */

// PLL Clock.
#define D_DD_PMC_UART_PLL_CLOCK_100MHZ		(100000000)				/**< PLL Clock:100[MHz] */
#define D_DD_PMC_UART_PLL_CLOCK_32KHZ		(32768)					/**< PLL Clock:32[kHz] */

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special
#endif

/*----------------------------------------------------------------------*/
/* Enumeration															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
/** Multi processor mode activation. */
typedef enum{
	E_DD_PMC_UART_MODE_MULTI_DIS	= 0,		/**< Asynchronization multiprocessor mode not active */
	E_DD_PMC_UART_MODE_MULTI_MASTER,			/**< Asynchronization multiprocessor mode active(Master) */
	E_DD_PMC_UART_MODE_MULTI_SLAVE,				/**< Asynchronization multiprocessor mode active(Slave) */
} E_DD_PMC_UART_MODE_MULTI_ACT;


#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special
#endif

/*----------------------------------------------------------------------*/
/* Structure															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
/* Uart ring buffer structure */
typedef struct {
	UINT32		r_read_pos;		// [receive] read position
	UINT32		r_write_pos;	// [receive] write position
	UINT32		r_size;			// [receive] write size
	CHAR		r_flag;			// [receive] use flag
	UINT32		s_read_pos;		// [store] read position
	UINT32		s_write_pos;	// [store] write position
	ULONG		s_overlap_cnt;	// [store] overlap count
	UINT32		s_size;			// [store] write size
	CHAR		s_flag;			// [store] use flag
}T_DD_PMC_UART_BUFFER_INFO;


/* Uart control information */
typedef struct {
	UCHAR							force_stop_flg;		/**< Force stop Flag */
	E_DD_PMC_UART_MODE_MULTI_ACT	multi_active_flg;	/**< Malti Processor mode active Flag */
	UCHAR							multi_slave_addr;	/**< Malti Processor mode Slave address */
	VP_CALLBACK						psend_callback;		/**< Send callback function pointer */
	VP_CALLBACK						preceive_callback;	/**< Receive callback function pointer */
}T_DD_PMC_UART_INFO;



#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special
#endif

/*----------------------------------------------------------------------*/
/* Global Data															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
// UART Management table
static volatile T_DD_PMC_UART_MNG gDD_PMC_Uart_Mng;

// UART Ring Buffer table
static volatile T_DD_PMC_UART_BUFFER_INFO gDD_PMC_Uart_Buff_Info;

/* Flag to make it not access address that no one sets.									*
 * When the handler starts before reception/transmission buffer is set, it accesses 0.	*/
static volatile UCHAR gDD_PMC_Uart_Flag = 0;

// Uart control information
static volatile T_DD_PMC_UART_INFO gDD_PMC_Uart_Info;

// DMA channel number
static volatile UCHAR gDD_PMC_SPI_Uart_DMA_Ch = D_DD_PMC_HDMAC_CH_NUM_MAX;

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special
#endif

/*----------------------------------------------------------------------*/
/* Macro																*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
/* Nothing Special */

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
#define D_DD_PMC_UART_DMACA_IS_BASE		(D_DD_PMC_HDMAC_IS_IDREQ_0)

#endif

/*----------------------------------------------------------------------*/
/* Local Function														*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
static INT32 dd_pmc_uart_check_stopping_conditions( VOID )
{
	if(gDD_PMC_Uart_Info.force_stop_flg == 1){
		gDD_PMC_Uart_Info.force_stop_flg = 0;
		return D_DD_PMC_UART_FORCE_STOP;
	}

	return D_DDIM_OK;
}

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
static INT32 dd_pmc_uart_dma_copy( UCHAR dma_ch, ULONG src_addr, ULONG dst_addr, ULONG trns_size );
static VOID dd_pmc_uart_hdmac_callback( UCHAR dma_ch, USHORT* const status );

static INT32 dd_pmc_uart_dma_copy( UCHAR dma_ch, ULONG src_addr, ULONG dst_addr, ULONG trns_size )
{
	INT32						ret;
	T_DD_PMC_HDMAC_CTRL_TRNS	dma_ctrl_trns;

	dma_ctrl_trns.mode.input_sel	= D_DD_PMC_UART_DMACA_IS_BASE + 1;
	dma_ctrl_trns.mode.mode_sel		= D_DD_PMC_HDMAC_MS_DEMAND;
	dma_ctrl_trns.mode.src_fix		= D_DD_PMC_HDMAC_FS_INCR;
	dma_ctrl_trns.mode.dst_fix		= D_DD_PMC_HDMAC_FD_FIX;
	dma_ctrl_trns.mode.beat_type	= D_DD_PMC_HDMAC_BT_NORMAL;

	dma_ctrl_trns.size.trns_width	= D_DD_PMC_HDMAC_TW_BYTE;
	dma_ctrl_trns.size.trns_size	= trns_size;
	dma_ctrl_trns.size.src_addr		= src_addr;
	dma_ctrl_trns.size.dst_addr		= dst_addr;

	ret = Dd_PMC_HDMAC_Ctrl_Trns( dma_ch, &dma_ctrl_trns );
	if( ret == D_DDIM_OK ){
		ret = Dd_PMC_HDMAC_Start_Async( dma_ch, (VP_CALLBACK)dd_pmc_uart_hdmac_callback );
		if( ret != D_DDIM_OK ){
			Ddim_Print(("Dd_PMC_HDMAC_Start_Async() error. ret=0x%x\n", ret));
			return ret;
		}
	}
	else{
		Ddim_Print(("Dd_PMC_HDMAC_Ctrl_Trns() error. ret=0x%x\n", ret));
		return ret;
	}

	return ret;
}

static VOID dd_pmc_uart_hdmac_callback( UCHAR dma_ch, USHORT* const status )
{
	INT32	ret = D_DDIM_OK;
	INT32	ret2;
	T_DD_PMC_HDMAC_TRNS_SIZE	dma_size;
	
	// End DMA transfer process.
	IO_PMC.UART.FCR.bit.FTIE = 0;
	dd_pmc_uart_dsb();
	
	if (*status != D_DD_PMC_HDMAC_SS_NORMAL_END) {
		// status error.
		return;
	}
	
	// no send data (data size = 0)
	if (gDD_PMC_Uart_Buff_Info.s_size == 0) {
		while( IO_PMC.UART.SSR.bit.__TBI == 0 ) {
			DDIM_User_Dly_Tsk(1);		// wait until TDR empty
			ret2 = dd_pmc_uart_check_stopping_conditions();
			if( ret2 != D_DDIM_OK ){
				return;
			}
		}
		
		if( gDD_PMC_Uart_Info.force_stop_flg == 1 ) {
			gDD_PMC_Uart_Info.force_stop_flg = 0;
		}
		return;
	}

	// SpinLock.
	Dd_ARM_Critical_Section_Start();
	
	// Set DMA data.
	dma_size.trns_width = D_DD_PMC_HDMAC_TW_BYTE;
	if( (gDD_PMC_Uart_Buff_Info.s_write_pos <= gDD_PMC_Uart_Buff_Info.s_read_pos) && (gDD_PMC_Uart_Buff_Info.s_flag == 1) ) {
		dma_size.trns_size = gDD_PMC_Uart_Mng.send_buff_size - gDD_PMC_Uart_Buff_Info.s_read_pos;
	}
	else {
		dma_size.trns_size = gDD_PMC_Uart_Buff_Info.s_size;
	}
	dma_size.src_addr = (ULONG)(gDD_PMC_Uart_Mng.send_buff_addr + gDD_PMC_Uart_Buff_Info.s_read_pos);
	dma_size.dst_addr = (ULONG)(&(IO_PMC.UART.DR));
	
	// SpinUnLock.
	Dd_ARM_Critical_Section_End();
	
	ret = Dd_PMC_HDMAC_Set_Trns_Size( dma_ch, &dma_size );
	if( ret == D_DDIM_OK ){
		// Start DMA
		ret = Dd_PMC_HDMAC_Start_Async( dma_ch, (VP_CALLBACK)dd_pmc_uart_hdmac_callback );
		if( ret == D_DDIM_OK ){
			// Start DMA by UART FIFO interrupt.
			IO_PMC.UART.FCR.bit.FTIE = 1;
			dd_pmc_uart_dsb();

			// SpinLock.
			Dd_ARM_Critical_Section_Start();
			
			// Increment read position.
			gDD_PMC_Uart_Buff_Info.s_read_pos += dma_size.trns_size;
			gDD_PMC_Uart_Buff_Info.s_size -= dma_size.trns_size;

			if( gDD_PMC_Uart_Buff_Info.s_read_pos >= gDD_PMC_Uart_Mng.send_buff_size ){
				gDD_PMC_Uart_Buff_Info.s_read_pos -= gDD_PMC_Uart_Mng.send_buff_size;
				gDD_PMC_Uart_Buff_Info.s_flag--;		// The flag is dropped
			}
			
			// SpinUnLock.
			Dd_ARM_Critical_Section_End();
		}
		else {
			Ddim_Print(("Dd_PMC_HDMAC_Start_Async() error. ret=0x%x\n", ret));
		}
	}
	else {
		Ddim_Print(("Dd_PMC_HDMAC_Set_Trns_Size() error. ret=0x%x\n", ret));
	}
	
	if( ret != D_DDIM_OK ){
		// End DMA transfer process.
		IO_PMC.UART.FCR.bit.FTIE = 0;
		dd_pmc_uart_dsb();
		
		while( IO_PMC.UART.SSR.bit.__TBI == 0 ) {
			DDIM_User_Dly_Tsk(1);		// wait until TDR empty
			ret2 = dd_pmc_uart_check_stopping_conditions();
			if( ret2 != D_DDIM_OK ){
				return;
			}
		}
		
		if( gDD_PMC_Uart_Info.force_stop_flg == 1 ) {
			gDD_PMC_Uart_Info.force_stop_flg = 0;
		}
	}
}
#endif

/*----------------------------------------------------------------------*/
/* Grobal Function														*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
/**
 * @brief  The value specified by the argument is set to the register of UART.
 * @param  T_DD_PMC_UART_MNG* uart_mng
 * @return INT32  D_DDIM_OK/D_DD_PMC_UART_INPUT_PARAM_ERROR
 */
INT32 Dd_PMC_UART_Ctrl( T_DD_PMC_UART_MNG const* const uart_mng )
{
	INT32 count;
	INT32 baud_rate;
	INT32 clock;

#ifdef CO_PARAM_CHECK
	if( uart_mng == NULL ){
		Ddim_Assertion(("UART input param error. [uart_mng] = NULL\n"));
		return D_DD_PMC_UART_INPUT_PARAM_ERROR;
	}
	if( uart_mng->mode == E_DD_PMC_UART_MODE_MULTI
	&& !( uart_mng->data_length == E_DD_PMC_UART_DATA_LENGTH_8 || uart_mng->data_length == E_DD_PMC_UART_DATA_LENGTH_7 )
	){
		Ddim_Assertion(("UART input param error. [mode] = %d, [data_length] = %d\n", uart_mng->mode, uart_mng->data_length));
		return D_DD_PMC_UART_INPUT_PARAM_ERROR;
	}
#endif
	
	gDD_PMC_SPI_Uart_DMA_Ch = D_DD_PMC_HDMAC_CH_NUM_MAX;
	
	baud_rate = (INT32)uart_mng->baud_rate;

	// The value gotten by the argument is set to a global table.
	gDD_PMC_Uart_Mng.baud_rate			= uart_mng->baud_rate;			// Baud rate
	gDD_PMC_Uart_Mng.receive_buff_addr	= uart_mng->receive_buff_addr;	// Receive buffer address
	gDD_PMC_Uart_Mng.receive_buff_size	= uart_mng->receive_buff_size;	// Receive buffer size
	gDD_PMC_Uart_Mng.send_buff_addr		= uart_mng->send_buff_addr;		// Receive buffer address
	gDD_PMC_Uart_Mng.send_buff_size		= uart_mng->send_buff_size;		// Receive buffer size
	gDD_PMC_Uart_Mng.auto_echo			= uart_mng->auto_echo;			// Auto echo
	gDD_PMC_Uart_Mng.save_buff			= uart_mng->save_buff;			// Save to the buffer

	// start flag initialize
	gDD_PMC_Uart_Flag = 1;

	/*-------------------------------*/
	/* Initialization of ring buffer */
	/*-------------------------------*/
	// Reception buffer initialization
	memset( gDD_PMC_Uart_Mng.receive_buff_addr, 0, gDD_PMC_Uart_Mng.receive_buff_size );
	gDD_PMC_Uart_Buff_Info.r_read_pos = 0;
	gDD_PMC_Uart_Buff_Info.r_write_pos = 0;
	gDD_PMC_Uart_Buff_Info.r_size = 0;
	gDD_PMC_Uart_Buff_Info.r_flag = 0;

	// Transmission buffer initialization
	memset( gDD_PMC_Uart_Mng.send_buff_addr, 0, gDD_PMC_Uart_Mng.send_buff_size );
	gDD_PMC_Uart_Buff_Info.s_read_pos = 0;
	gDD_PMC_Uart_Buff_Info.s_write_pos = 0;
	gDD_PMC_Uart_Buff_Info.s_size = 0;
	gDD_PMC_Uart_Buff_Info.s_flag = 0;

	// Uart control information initialization
	gDD_PMC_Uart_Info.force_stop_flg	= 0;
	gDD_PMC_Uart_Info.multi_active_flg	= E_DD_PMC_UART_MODE_MULTI_DIS;
	gDD_PMC_Uart_Info.multi_slave_addr	= 0;

	/*----------------------*/
	/* Setting of UART Mode */
	/*----------------------*/
	if ( Dd_PMC_CRG11_Get_CRPLC_PLLBYPASS()){
		// 32KHz.
		clock = D_DD_PMC_UART_PLL_CLOCK_32KHZ / (Dd_PMC_CRG11_Get_CRDM0_DIVMODE() + 1);
	}
	else {
		// 100MHz.
		clock = D_DD_PMC_UART_PLL_CLOCK_100MHZ / (Dd_PMC_CRG11_Get_CRDM0_DIVMODE() + 1);
	}
	count = (clock / baud_rate) - 1;

	IO_PMC.UART.SCR.byte  = 0x00;			// RIE, TIE,TBIE Mask
	IO_PMC.UART.SCR.byte  = 0x80;			// UART Macro initialize
	IO_PMC.UART.SMR.byte  = 0x01;
	IO_PMC.UART.ESCR.byte = 0x00;
	IO_PMC.UART.SSR.byte  = 0x80;
	IO_PMC.UART.FCR.hword = 0x0000;

	if( uart_mng->mode == E_DD_PMC_UART_MODE_MULTI ){
		IO_PMC.UART.SMR.bit.MD	= 1;
		IO_PMC.UART.ESCR.bit.PEN	= 0;
	}
	else{
		// Normal mode
		IO_PMC.UART.SMR.bit.MD	= 0;

		if( uart_mng->parity_bit == E_DD_PMC_UART_PARITY_BIT_EVEN ){
			IO_PMC.UART.ESCR.bit.PEN	= 1;
			IO_PMC.UART.ESCR.bit.P = 0;
		}
		else if( uart_mng->parity_bit == E_DD_PMC_UART_PARITY_BIT_ODD ){
			IO_PMC.UART.ESCR.bit.PEN	= 1;
			IO_PMC.UART.ESCR.bit.P = 1;
		}
		else{
			// E_DD_PMC_UART_PARITY_BIT_NONE
			IO_PMC.UART.ESCR.bit.PEN	= 0;
		}
	}

	IO_PMC.UART.ESCR.bit.INV	= uart_mng->inv_nrz;

	IO_PMC.UART.BGR.hword = (SHORT)count;
	IO_PMC.UART.BGR.bit.EXT = 0;	// internal clock only

	IO_PMC.UART.SMR.bit.BDS	= (UCHAR)uart_mng->bit_direction;
	IO_PMC.UART.SMR.bit.SBL	= (UCHAR)uart_mng->stop_bit_length;

	IO_PMC.UART.ESCR.bit.L = uart_mng->data_length;

	if( uart_mng->fifo_ctrl == NULL ){
		IO_PMC.UART.FCR.hword = 0x000C;	// FIFO not used and FIFO reset
		return D_DDIM_OK;
	}

	IO_PMC.UART.FCR.hword			= 0x000C;						// Initialize
	IO_PMC.UART.FCR.bit.FLSTE		= uart_mng->fifo_ctrl->flste;	// data-lost check permmision bit
	IO_PMC.UART.FCR.bit.FSEL		= uart_mng->fifo_ctrl->fsel;	// fifo selection bit

	IO_PMC.UART.FCR.bit.FSET		= uart_mng->fifo_ctrl->fset;	// fifo transfer reload pointer storing bit

	IO_PMC.UART.FCR.bit.FE2		= uart_mng->fifo_ctrl->fe2;
	IO_PMC.UART.FCR.bit.FE1		= uart_mng->fifo_ctrl->fe1;

	if( ((uart_mng->fifo_ctrl->fsel == 0) && (uart_mng->fifo_ctrl->fe2 == 1))
	||	 ((uart_mng->fifo_ctrl->fsel == 1) && (uart_mng->fifo_ctrl->fe1 == 1)) ){
		IO_PMC.UART.FCR.bit.FRIIE = 1;								// Receive FIFO idle detection enable bit
	}

	IO_PMC.UART.FBYTE.hword		= 0x0000;						// FBYE initial value

	if( uart_mng->fifo_ctrl->fsel == 0 ){
		IO_PMC.UART.FBYTE.byte[1] = uart_mng->fifo_ctrl->fbyte_recv;
	}
	else{
		IO_PMC.UART.FBYTE.byte[0] = uart_mng->fifo_ctrl->fbyte_recv;
	}

	return D_DDIM_OK;
}


/**
 * @brief  The value specified by the argument is get from the register of UART.
 * @param  T_DD_PMC_UART_MNG* uart_mng
 * @return INT32  D_DDIM_OK/D_DD_PMC_UART_INPUT_PARAM_ERROR
 */
INT32 Dd_PMC_UART_Get_Ctrl( T_DD_PMC_UART_MNG* const uart_mng )
{
#ifdef CO_PARAM_CHECK
	if( uart_mng == NULL ){
		Ddim_Assertion(("UART input param error. [uart_mng] = NULL\n"));
		return D_DD_PMC_UART_INPUT_PARAM_ERROR;
	}
#endif

	uart_mng->baud_rate 		= gDD_PMC_Uart_Mng.baud_rate;
	uart_mng->receive_buff_addr = gDD_PMC_Uart_Mng.receive_buff_addr;
	uart_mng->receive_buff_size = gDD_PMC_Uart_Mng.receive_buff_size;
	uart_mng->send_buff_addr	= gDD_PMC_Uart_Mng.send_buff_addr;
	uart_mng->send_buff_size	= gDD_PMC_Uart_Mng.send_buff_size;
	uart_mng->auto_echo			= gDD_PMC_Uart_Mng.auto_echo;
	uart_mng->save_buff			= gDD_PMC_Uart_Mng.save_buff;

	uart_mng->mode				= (E_DD_PMC_UART_MODE)IO_PMC.UART.SMR.bit.MD;
	uart_mng->bit_direction 	= (E_DD_PMC_UART_BIT_DIR)IO_PMC.UART.SMR.bit.BDS;
	uart_mng->stop_bit_length	= (E_DD_PMC_UART_STOP_BIT)IO_PMC.UART.SMR.bit.SBL;
	uart_mng->data_length		= (E_DD_PMC_UART_DATA_LENGTH)IO_PMC.UART.ESCR.bit.L;
	if( IO_PMC.UART.ESCR.bit.PEN == 1 ){
		if( IO_PMC.UART.ESCR.bit.P == 1 ){
			uart_mng->parity_bit = E_DD_PMC_UART_PARITY_BIT_ODD;
		}
		else{
			uart_mng->parity_bit = E_DD_PMC_UART_PARITY_BIT_EVEN;
		}
	}
	else{
		uart_mng->parity_bit = E_DD_PMC_UART_PARITY_BIT_NONE;
	}

	if( uart_mng->fifo_ctrl == NULL ){
		return D_DDIM_OK;
	}

	uart_mng->inv_nrz = IO_PMC.UART.ESCR.bit.INV;

	uart_mng->fifo_ctrl->fsel	= IO_PMC.UART.FCR.bit.FSEL;
	uart_mng->fifo_ctrl->flste	= IO_PMC.UART.FCR.bit.FLSTE;
	uart_mng->fifo_ctrl->fset	= IO_PMC.UART.FCR.bit.FSET;
	uart_mng->fifo_ctrl->fe2	= IO_PMC.UART.FCR.bit.FE2;
	uart_mng->fifo_ctrl->fe1	= IO_PMC.UART.FCR.bit.FE1;
	if( uart_mng->fifo_ctrl->fsel == 0 ){
		uart_mng->fifo_ctrl->fbyte_recv = IO_PMC.UART.FBYTE.bit.__FIFO2;
	}
	else{
		uart_mng->fifo_ctrl->fbyte_recv = IO_PMC.UART.FBYTE.bit.__FIFO1;
	}

	return D_DDIM_OK;
}


INT32 Dd_PMC_UART_Set_Baudrate( USHORT baud_rate )
{
	IO_PMC.UART.BGR.hword = baud_rate;
	return D_DDIM_OK;
}


INT32 Dd_PMC_UART_Get_Baudrate( USHORT* baud_rate )
{
#ifdef CO_PARAM_CHECK
	if( baud_rate == NULL ){
		Ddim_Assertion(("UART input param error. [baud_rate] = NULL\n"));
		return D_DD_PMC_UART_INPUT_PARAM_ERROR;
	}
#endif
	*baud_rate = IO_PMC.UART.BGR.hword;
	return D_DDIM_OK;
}


INT32 Dd_PMC_UART_Reset_Baudrate( VOID )
{
	INT32 baud_rate;
	INT32 count;
	INT32 clock;

	baud_rate = gDD_PMC_Uart_Mng.baud_rate;
	clock = D_DD_PMC_UART_PLL_CLOCK_100MHZ / (Dd_PMC_CRG11_Get_CRDM0_DIVMODE() + 1);
	count = (clock /  baud_rate) - 1;
	IO_PMC.UART.BGR.hword = (unsigned short)count;
	return D_DDIM_OK;
}


INT32 Dd_PMC_UART_Save_Send_FIFO_Pointer( UCHAR lost_detect )
{
#ifdef CO_PARAM_CHECK
	if( (lost_detect != 0) && (lost_detect != 1) ){
		Ddim_Assertion(("UART input param error. [lost_detect] = %d\n", lost_detect));
		return D_DD_PMC_UART_INPUT_PARAM_ERROR;
	}
#endif

	// Check exist data in send fifo
	if( IO_PMC.UART.FBYTE.byte[IO_PMC.UART.FCR.bit.FSEL] != 0 ){
		return D_DD_PMC_UART_DATA_EXIST_ERROR;
	}

	// Save Read Pointer
	IO_PMC.UART.FCR.bit.FSET = 1;

	// Enable/Disable data lost detection (FLST)
	IO_PMC.UART.FCR.bit.FLSTE = lost_detect;

	return D_DDIM_OK;
}


INT32 Dd_PMC_UART_Reload_Send_FIFO_Pointer( VOID )
{
	UCHAR fe1;
	UCHAR fe2;

	if( IO_PMC.UART.FCR.bit.FLST == 1 ){
		// Reload data lost
		return D_DD_PMC_UART_OVERWRITE_ERROR;
	}

	// Keep to temporary
	fe1	= IO_PMC.UART.FCR.bit.FE1;
	fe2	= IO_PMC.UART.FCR.bit.FE2;

	// Disable send/receive
	IO_PMC.UART.FCR.bit.FE1	= 0;
	IO_PMC.UART.FCR.bit.FE2	= 0;
	IO_PMC.UART.SCR.bit.TIE	= 0;
	IO_PMC.UART.SCR.bit.TBIE	= 0;
	IO_PMC.UART.FCR.bit.FTIE	= 0;

	// Reload Send FIFO
	IO_PMC.UART.FCR.bit.FLD	= 1;

	// Enable send permission
	IO_PMC.UART.SMR.bit.SOE	= 1;
	IO_PMC.UART.SCR.bit.TXE	= 1;

	// Set keep value
	IO_PMC.UART.FCR.bit.FE1	= fe1;
	IO_PMC.UART.FCR.bit.FE2	= fe2;

	// Subtract the number of resend   ???
//	if( IO_PMC.UART.FBYTE.byte[IO_PMC.UART.FCR.bit.FSEL] >= gDD_PMC_UART_Info.send_pos ){
//		gDD_PMC_UART_Info.send_pos -= IO_PMC.UART.FBYTE.byte[IO_PMC.UART.FCR.bit.FSEL];
//	}

	if( gDD_PMC_Uart_Info.psend_callback ){	// Interrupt enable?
		IO_PMC.UART.FCR.bit.FDRQ = 0;
		IO_PMC.UART.FCR.bit.FTIE = 1;
	}

	dd_pmc_uart_dsb();

	return D_DDIM_OK;
}


INT32 Dd_PMC_UART_Get_Reload_Status( VOID )
{
	return IO_PMC.UART.FCR.bit.FLD;
}


INT32 Dd_PMC_UART_Reset_FIFO( UCHAR fifo_num )
{
	UCHAR txe;
	UCHAR rxe;
	UCHAR ftie;

#ifdef CO_PARAM_CHECK
	if( (fifo_num != 1) && (fifo_num != 2) && (fifo_num != 3) ){
		Ddim_Assertion(("UART input param error. [fifo_num] = %d\n", fifo_num));
		return D_DD_PMC_UART_INPUT_PARAM_ERROR;
	}
#endif
	// Keep to temporary
	txe = IO_PMC.UART.SCR.bit.TXE;
	rxe = IO_PMC.UART.SCR.bit.RXE;
	ftie = IO_PMC.UART.FCR.bit.FTIE;

	// Disable send/receive
	IO_PMC.UART.SCR.bit.TXE	= 0;
	IO_PMC.UART.SCR.bit.RXE	= 0;
	IO_PMC.UART.FCR.bit.FTIE	= 0;

	// Reset FIFO
	IO_PMC.UART.FCR.hword |= fifo_num << 2;		// D_DD_PMC_UART_SELECT_FIFO_1		(1)
												// D_DD_PMC_UART_SELECT_FIFO_2		(2)
												// D_DD_PMC_UART_SELECT_FIFO_BOTH	(3)

	dd_pmc_uart_dsb();

	// Set keep value
	IO_PMC.UART.SCR.bit.TXE		= txe;
	IO_PMC.UART.SCR.bit.RXE		= rxe;
	IO_PMC.UART.FCR.bit.FTIE	= ftie;

	dd_pmc_uart_dsb();

	return D_DDIM_OK;
}


/**
 * @brief  The UART sending and receiving processing begins.
 * @param  VP_CALLBACK psend_callback/VP_CALLBACK preceive_callback
 * @return INT32  D_DDIM_OK/D_DD_PMC_UART_INPUT_PARAM_ERROR
 */
INT32 Dd_PMC_UART_Start( VP_CALLBACK psend_callback, VP_CALLBACK preceive_callback )
{
	// Send callback function pointer
	gDD_PMC_Uart_Info.psend_callback = psend_callback;
	
	// Receive callback function pointer
	gDD_PMC_Uart_Info.preceive_callback = preceive_callback;
	if( gDD_PMC_Uart_Info.preceive_callback != NULL ) {
		IO_PMC.UART.SCR.bit.RIE = 1;
	}
	
	IO_PMC.UART.SCR.byte |= 0x03;

	dd_pmc_uart_dsb();

	return D_DDIM_OK;
}


/**
 * @brief	Stop sending/receiving data(force stop)
 * @return	INT32		D_DDIM_OK / D_DD_PMC_UART_INPUT_PARAM_ERROR
 */
INT32 Dd_PMC_UART_Stop( VOID )
{
	// Disable interrupt
	IO_PMC.UART.SCR.bit.RIE		= 0;
	IO_PMC.UART.SCR.bit.TIE		= 0;
	IO_PMC.UART.SCR.bit.TBIE	= 0;
	IO_PMC.UART.FCR.bit.FTIE	= 0;
	IO_PMC.UART.FCR.bit.FRIIE	= 0;

	// Disable FIFO
	IO_PMC.UART.FCR.bit.FE1	= 0;
	IO_PMC.UART.FCR.bit.FE2	= 0;

	IO_PMC.UART.SCR.bit.UPCL	= 1;								// Soft-Reset

	// Disable send/receive
	IO_PMC.UART.SCR.bit.TXE	= 0;
	IO_PMC.UART.SCR.bit.RXE	= 0;

	// DMA stop
	if ( gDD_PMC_SPI_Uart_DMA_Ch < D_DD_PMC_HDMAC_CH_NUM_MAX ) {
		Dd_PMC_HDMAC_Stop( gDD_PMC_SPI_Uart_DMA_Ch );
		
		// DMA ch Clear.
		gDD_PMC_SPI_Uart_DMA_Ch = D_DD_PMC_HDMAC_CH_NUM_MAX;
	}
	
	gDD_PMC_Uart_Info.force_stop_flg = 1;

	dd_pmc_uart_dsb();

	return D_DDIM_OK;
}


/**
 * @brief  The transmission data specified by the argument is set to the register for the UART transmission.
 * @param  CHAR		put_char
 * @return INT32	D_DDIM_OK / D_DD_PMC_UART_INPUT_PARAM_ERROR
 */
INT32 Dd_PMC_UART_Put_Char( CHAR put_char )
{
	INT32 ret;

	if( IO_PMC.UART.SCR.bit.TXE == 0 ){
		return D_DD_PMC_UART_STOPPED;
	}

	if( ((IO_PMC.UART.FCR.bit.FSEL == 0) && (IO_PMC.UART.FCR.bit.FE1 == 1)) || 
	   ((IO_PMC.UART.FCR.bit.FSEL == 1) && (IO_PMC.UART.FCR.bit.FE2 == 1)) ){
		// FIFO use
		while( IO_PMC.UART.FCR.bit.FDRQ == 0 ){
			ret = dd_pmc_uart_check_stopping_conditions();
			if( ret != D_DDIM_OK ){
				return ret;
			}
		}

		IO_PMC.UART.DR.hword = put_char;

		if( gDD_PMC_Uart_Info.psend_callback != NULL ){
			// Interruput is enable
			IO_PMC.UART.FCR.bit.FDRQ = 0;
			IO_PMC.UART.FCR.bit.FTIE = 1;
		}
	}
	else{
		// FIFO not use
		while( IO_PMC.UART.SSR.bit.__TDRE == 0 ){
			ret = dd_pmc_uart_check_stopping_conditions();
			if( ret != D_DDIM_OK ){
				return ret;
			}
		}
		if( gDD_PMC_Uart_Info.force_stop_flg == 1 ){
			gDD_PMC_Uart_Info.force_stop_flg = 0;
			return D_DD_PMC_UART_FORCE_STOP;
		}

		IO_PMC.UART.DR.hword = put_char;

		if( gDD_PMC_Uart_Info.psend_callback != NULL ){
			while( IO_PMC.UART.SSR.bit.__TDRE == 1 ){
				ret = dd_pmc_uart_check_stopping_conditions();
				if( ret != D_DDIM_OK ){
					return ret;
				}
				if (IO_PMC.UART.SSR.bit.__TBI == 1){
					break;
				}
			}
			// Interruput is enable
			IO_PMC.UART.SCR.bit.TIE = 1;
		}
	}

	dd_pmc_uart_dsb();

	return D_DDIM_OK;
}


/**
 * @brief  The data that wants to transmit to the transmission buffer is stored.
		   When the transmission buffer overflows, the overflow error is sent back.
 * @param  CHAR   str
 * @return INT32  D_DDIM_OK/D_DD_PMC_UART_OVERFLOW_ERROR
 */
INT32 Dd_PMC_UART_Set_Str( CHAR str )
{
	INT32 result;

	// SpinLock.
	Dd_ARM_Critical_Section_Start();
	
	if( ( gDD_PMC_Uart_Buff_Info.s_read_pos <= gDD_PMC_Uart_Buff_Info.s_write_pos ) && ( gDD_PMC_Uart_Buff_Info.s_flag == 1 ) ){
		result = D_DD_PMC_UART_OVERFLOW_ERROR;
	}
	else{
		gDD_PMC_Uart_Mng.send_buff_addr[gDD_PMC_Uart_Buff_Info.s_write_pos] = str;
		++gDD_PMC_Uart_Buff_Info.s_write_pos;
		++gDD_PMC_Uart_Buff_Info.s_size;

		if( gDD_PMC_Uart_Buff_Info.s_write_pos >= gDD_PMC_Uart_Mng.send_buff_size ){
			gDD_PMC_Uart_Buff_Info.s_write_pos -= gDD_PMC_Uart_Mng.send_buff_size;
			gDD_PMC_Uart_Buff_Info.s_flag++;		// The flag is hoisted
			gDD_PMC_Uart_Buff_Info.s_overlap_cnt++;
		}

		result = D_DDIM_OK;
	}
	
	// SpinUnLock.
	Dd_ARM_Critical_Section_End();
	
	return result;
}


/**
 * @brief  All the data that exists in the transmission buffer is transmitted.
		   The error is sent back when there is no data in the transmission buffer.
 * @return INT32  D_DDIM_OK/D_DD_PMC_UART_NO_SEND_DATA
 */
INT32 Dd_PMC_UART_Put_Str( VOID )
{
	CHAR	buff_data;
	INT32	send_size;
	INT32	result;

	if( IO_PMC.UART.SCR.bit.TXE == 0 ){
		return D_DD_PMC_UART_STOPPED;
	}

	if( gDD_PMC_Uart_Buff_Info.s_size == 0 ){
		result = D_DD_PMC_UART_NO_SEND_DATA;
	}
	else{
		// All the data that exists in the transmission buffer is transmitted
		for( send_size = gDD_PMC_Uart_Buff_Info.s_size; send_size > 0; send_size-- ){
			buff_data = *( gDD_PMC_Uart_Mng.send_buff_addr + gDD_PMC_Uart_Buff_Info.s_read_pos );
			result = Dd_PMC_UART_Put_Char( buff_data );
			if( result != D_DDIM_OK ){
				return result;
			}

			// SpinLock.
			Dd_ARM_Critical_Section_Start();
			
			++gDD_PMC_Uart_Buff_Info.s_read_pos;
			--gDD_PMC_Uart_Buff_Info.s_size;

			if( gDD_PMC_Uart_Buff_Info.s_read_pos >= gDD_PMC_Uart_Mng.send_buff_size ){
				gDD_PMC_Uart_Buff_Info.s_read_pos -= gDD_PMC_Uart_Mng.send_buff_size;
				gDD_PMC_Uart_Buff_Info.s_flag--;		// The flag is dropped
			}
			
			// SpinUnLock.
			Dd_ARM_Critical_Section_End();
		}
		result = D_DDIM_OK;
	}
	return result;
}


/**
 * @brief  Receive data is acquired from the UART receive data storage area.
 * @param  CHAR*  get_char
 * @return INT32  D_DDIM_OK/D_DD_PMC_UART_NO_RECEIVE/D_DD_PMC_UART_OVERFLOW_ERROR
 */
INT32 Dd_PMC_UART_Get_Char( CHAR* const get_char )
{
	UCHAR buff_data;
	INT32 result;

#ifdef CO_PARAM_CHECK
	if( get_char == NULL ){
		Ddim_Assertion(("UART input param error. [get_char] = NULL\n"));
		return D_DD_PMC_UART_INPUT_PARAM_ERROR;
	}
#endif
	if( gDD_PMC_Uart_Buff_Info.r_size == 0 ){
		result = D_DD_PMC_UART_NO_RECEIVE;
	}
	else if( (gDD_PMC_Uart_Buff_Info.r_read_pos <= gDD_PMC_Uart_Buff_Info.r_write_pos) && (gDD_PMC_Uart_Buff_Info.r_flag == 1) ){
		result = D_DD_PMC_UART_OVERFLOW_ERROR;
	}
	else{
		if( gDD_PMC_Uart_Flag == 1 ){
			// SpinLock.
			Dd_ARM_Critical_Section_Start();
			
			buff_data = *( gDD_PMC_Uart_Mng.receive_buff_addr + gDD_PMC_Uart_Buff_Info.r_read_pos );

			*get_char = buff_data;
			++gDD_PMC_Uart_Buff_Info.r_read_pos;
			--gDD_PMC_Uart_Buff_Info.r_size;

			if( gDD_PMC_Uart_Buff_Info.r_read_pos >= gDD_PMC_Uart_Mng.receive_buff_size ){
				gDD_PMC_Uart_Buff_Info.r_read_pos -= gDD_PMC_Uart_Mng.receive_buff_size;
				gDD_PMC_Uart_Buff_Info.r_flag--;		// The flag is dropped
			}
			
			// SpinUnLock.
			Dd_ARM_Critical_Section_End();
			
			result = D_DDIM_OK;
		}
		else{
			result = D_DD_PMC_UART_NO_RECEIVE;
		}
	}
	return result;
}


/**
 * @brief  Get the write pointer of send buffer.
 * @return INT32  write pointer
 */
ULONG Dd_PMC_UART_Get_Send_Write_Pointer_Addr( VOID )
{
	return (ULONG)gDD_PMC_Uart_Buff_Info.s_write_pos;
}

ULONG Dd_PMC_UART_Get_Send_Overlap_Count( VOID )
{
	return gDD_PMC_Uart_Buff_Info.s_overlap_cnt;
}


INT32 Dd_PMC_UART_Set_Slave_Addr( UCHAR slave_addr )
{
	gDD_PMC_Uart_Info.multi_slave_addr = slave_addr;
	return D_DDIM_OK;
}


INT32 Dd_PMC_UART_Send_Target_Slave_Addr( UCHAR slave_addr )
{
	INT32 ret;

	if( IO_PMC.UART.SMR.bit.MD == 0 ){	// Normal mode
		return D_DD_PMC_UART_MODE_UNMATCH;
	}

	if( IO_PMC.UART.SCR.bit.TXE == 0 ){
		return D_DD_PMC_UART_STOPPED;
	}

	if( ((IO_PMC.UART.FCR.bit.FSEL == 0) && (IO_PMC.UART.FCR.bit.FE1 == 1)) || 
	   ((IO_PMC.UART.FCR.bit.FSEL == 1) && (IO_PMC.UART.FCR.bit.FE2 == 1)) ){
		// FIFO use
		while( IO_PMC.UART.FCR.bit.FDRQ == 0 ){
			ret = dd_pmc_uart_check_stopping_conditions();
			if( ret != D_DDIM_OK ){
				return ret;
			}
		}

		IO_PMC.UART.DR.hword = (0x0100 | slave_addr);

		if( gDD_PMC_Uart_Info.psend_callback != NULL ){
			// Interruput is enable
			IO_PMC.UART.FCR.bit.FDRQ = 0;
			IO_PMC.UART.FCR.bit.FTIE = 1;
		}
	}
	else{
		// FIFO not use
		while( IO_PMC.UART.SSR.bit.__TDRE == 0 ){
			ret = dd_pmc_uart_check_stopping_conditions();
			if( ret != D_DDIM_OK ){
				return ret;
			}
		}
		if( gDD_PMC_Uart_Info.force_stop_flg == 1 ){
			gDD_PMC_Uart_Info.force_stop_flg = 0;
			return D_DD_PMC_UART_FORCE_STOP;
		}

		IO_PMC.UART.DR.hword = (0x0100 | slave_addr);

		if( gDD_PMC_Uart_Info.psend_callback != NULL ){
			while( IO_PMC.UART.SSR.bit.__TDRE == 1 ){
				ret = dd_pmc_uart_check_stopping_conditions();
				if( ret != D_DDIM_OK ){
					return ret;
				}
			}
			// Interruput is enable
			IO_PMC.UART.SCR.bit.TIE = 1;
		}
	}

	gDD_PMC_Uart_Info.multi_active_flg = E_DD_PMC_UART_MODE_MULTI_MASTER;

	dd_pmc_uart_dsb();

	return D_DDIM_OK;
}


/**
 * @brief  It is a function started when the UART transmission is completed.
 * @return VOID
 */
VOID Dd_PMC_UART_Int_Handler_Tx( VOID )
{
	if( IO_PMC.UART.SSR.bit.__TBI == 1 ){
		IO_PMC.UART.SCR.bit.TIE = 0;
		IO_PMC.UART.FCR.bit.FTIE = 0;

		dd_pmc_uart_dsb();

		if( ( gDD_PMC_Uart_Info.psend_callback != NULL ) && ( gDD_PMC_Uart_Flag == 1 ) ){
			( *gDD_PMC_Uart_Info.psend_callback )();
		}
	}
}


/**
 * @brief  It is a function started when the UART reception is completed.
 * @return VOID
 */
VOID Dd_PMC_UART_Int_Handler_Rx( VOID )
{
	CHAR	r_data;
	USHORT	r_addr;
	INT32	r_rslt;
	INT32	result;

	if( gDD_PMC_Uart_Flag == 1 ){
		r_rslt = ( IO_PMC.UART.SSR.byte & 0x38 );	// The reception result is acquired.
		
		// No error
		if ( r_rslt == 0 )
		{
			if( IO_PMC.UART.SMR.bit.MD == 1 ){	// Multi Processor mode
				r_addr = IO_PMC.UART.DR.hword;
				if( r_addr & D_DD_PMC_UART_DR_D8_BIT ){							// address
					if( (r_addr & 0x00FF) == (USHORT)gDD_PMC_Uart_Info.multi_slave_addr ){
						result = D_DD_PMC_UART_INT_STATUS_RECV_SLAVE_ADDR;
						gDD_PMC_Uart_Info.multi_active_flg = E_DD_PMC_UART_MODE_MULTI_SLAVE;
						if ( gDD_PMC_Uart_Info.preceive_callback != NULL ){
							( *gDD_PMC_Uart_Info.preceive_callback )( &result );
						}
						return;		// Communication start
					}
					else{
						if( gDD_PMC_Uart_Info.multi_active_flg == E_DD_PMC_UART_MODE_MULTI_SLAVE ){
							gDD_PMC_Uart_Info.multi_active_flg = E_DD_PMC_UART_MODE_MULTI_DIS;		// Slave address unmatch
//								Ddim_Print(("Slave address unmatch addr=0x%x\n", r_addr));
						}
						return;
					}
				}
				else{
					if( gDD_PMC_Uart_Info.multi_active_flg == E_DD_PMC_UART_MODE_MULTI_DIS ){
//							Ddim_Print(("Data to other data=%s\n", r_addr));
						return;		// Data to other
					}
				}
			}

			result = D_DD_PMC_UART_INT_STATUS_RECV_CHAR;
			r_data = (CHAR)IO_PMC.UART.DR.byte[0];		// Receive data acquisition

			if( gDD_PMC_Uart_Mng.auto_echo == E_DD_PMC_UART_AUTO_ECHO_ON ){
				if( r_data == '\r' || r_data == '\n' ){
					Dd_PMC_UART_Put_Char( '\r' );
					Dd_PMC_UART_Put_Char( '\n' );
					result = D_DD_PMC_UART_INT_STATUS_RECV_ENTER;
				}
				else{
					// echo
					Dd_PMC_UART_Put_Char( r_data );
				}
			}
			else{
				result = (INT32)r_data;
			}
			if( gDD_PMC_Uart_Info.preceive_callback != NULL ){
				( *gDD_PMC_Uart_Info.preceive_callback )( &result );	// Reception result is passed to the user here
			}

			if( gDD_PMC_Uart_Mng.save_buff == E_DD_PMC_UART_SAVE2BUFFER_EN ){
				// SpinLock.
				Dd_ARM_Critical_Section_Start();
				
				gDD_PMC_Uart_Mng.receive_buff_addr[gDD_PMC_Uart_Buff_Info.r_write_pos] = r_data;
				++gDD_PMC_Uart_Buff_Info.r_write_pos;
				++gDD_PMC_Uart_Buff_Info.r_size;

				if( gDD_PMC_Uart_Buff_Info.r_write_pos >= gDD_PMC_Uart_Mng.receive_buff_size ){
					gDD_PMC_Uart_Buff_Info.r_write_pos -= gDD_PMC_Uart_Mng.receive_buff_size;
					gDD_PMC_Uart_Buff_Info.r_flag++;		// The flag is hoisted
				}
				
				// SpinUnLock.
				Dd_ARM_Critical_Section_End();
			}
		}
		else if (r_rslt & 0x38)
		{
			// Clear once and for all the error bit
			IO_PMC.UART.SSR.byte |= D_DD_PMC_UART_SSR_REC_BIT;
			dd_pmc_uart_dsb();
		
			// Parity error
			if (r_rslt & 0x20)
			{
				result = D_DD_PMC_UART_INT_STATUS_PARITY_ERROR;
				if( gDD_PMC_Uart_Info.preceive_callback != NULL ){
					( *gDD_PMC_Uart_Info.preceive_callback )( &result );		// Reception result is passed to the user here
				}
			}

			// Over-run error
			if (r_rslt & 0x08)
			{
				result = D_DD_PMC_UART_INT_STATUS_OVERRUN_ERROR;
				if( gDD_PMC_Uart_Info.preceive_callback != NULL ){
					( *gDD_PMC_Uart_Info.preceive_callback )( &result );		// Reception result is passed to the user here
				}
			}

			// Framing error
			if (r_rslt & 0x10)
			{
				result = D_DD_PMC_UART_INT_STATUS_FRAMING_ERROR;
				if( gDD_PMC_Uart_Info.preceive_callback != NULL ){
					( *gDD_PMC_Uart_Info.preceive_callback )( &result );		// Reception result is passed to the user here
				}
			}
		}
	}	// It annuls it because Dd_PMC_UART_Ctrl() is not called, except when gDD_PMC_Uart_Flag is 1.
}


#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
/**
 * @brief  The value specified by the argument is set to the register of UART.
 * @param  T_DD_PMC_UART_MNG_SIMPLE* uart_mng_simple
 * @return INT32  D_DD_OK/D_DD_PMC_UART_INPUT_PARAM_ERROR
 */
INT32 Dd_PMC_UART_Initialize_Simple( T_DD_PMC_UART_MNG_SIMPLE const *const uart_mng_simple )
{
	INT32				ret;
	T_DD_PMC_UART_MNG	uart_mng;

#ifdef CO_PARAM_CHECK
	if( uart_mng_simple == NULL ){
		Ddim_Assertion(("UART input param error. [uart_mng_simple] = NULL\n"));
		return D_DD_PMC_UART_INPUT_PARAM_ERROR;
	}
#endif

	// The value gotten by the argument is set to a management table.
	uart_mng.baud_rate			= uart_mng_simple->baud_rate;			// Baud rate
	uart_mng.receive_buff_addr	= uart_mng_simple->receive_buff_addr;	// Receive buffer address
	uart_mng.receive_buff_size	= uart_mng_simple->receive_buff_size;	// Receive buffer size
	uart_mng.send_buff_addr		= uart_mng_simple->send_buff_addr;		// Send_buff_addr
	uart_mng.send_buff_size		= uart_mng_simple->send_buff_size;		// Send buffer size
	uart_mng.auto_echo			= uart_mng_simple->auto_echo;			// Auto Echo
	uart_mng.save_buff			= uart_mng_simple->save_buff;			// Save to the buffer
	uart_mng.mode				= E_DD_PMC_UART_MODE_NORMAL;			// UART Normal Mode
	uart_mng.bit_direction		= E_DD_PMC_UART_BIT_DIR_LSB_FIRST;		// Transferring Direction, LSB first or MSB first
	uart_mng.stop_bit_length	= uart_mng_simple->stop_bit_length;		// Stop bit length
	uart_mng.data_length		= uart_mng_simple->data_length;			// Data Length
	uart_mng.parity_bit			= uart_mng_simple->parity_bit;			// Parity bit type
	uart_mng.inv_nrz			= 0;									// NRZ
	uart_mng.fifo_ctrl			= NULL;									// FIFO Setting

	ret = Dd_PMC_UART_Ctrl( &uart_mng );

	return ret;
}

//---------------------------- colabo section ----------------------------
/**
 * @brief  All the data that exists in the transmission buffer is transmitted via DMA and UART FIFO.
		   The error is sent back when there is no data in the transmission buffer.
 * @param  UCHAR  dma_ch
 * @return INT32  D_DDIM_OK/D_DD_PMC_UART_NO_SEND_DATA
 */
INT32 Dd_PMC_UART_Put_Str_DMA( UCHAR dma_ch )
{
	UINT32	send_size;
	INT32	ret = D_DDIM_OK;
	INT32	ret2;
	ULONG	src_addr, dst_addr;

#ifdef CO_PARAM_CHECK
	if( dma_ch >= D_DD_PMC_HDMAC_CH_NUM_MAX ){
		Ddim_Assertion(("UART input param error. [dma_ch] = %d\n", dma_ch));
		return D_DD_PMC_UART_INPUT_PARAM_ERROR;
	}
#endif

	gDD_PMC_SPI_Uart_DMA_Ch	= dma_ch;
	
	if( gDD_PMC_Uart_Buff_Info.s_size == 0 ){
		ret = D_DD_PMC_UART_NO_SEND_DATA;
	}
	else{
		// Sets transmission FIFO, when not set with Dd_PMC_UART_Ctrl().
		if( (( IO_PMC.UART.FCR.bit.FSEL == 0 ) && ( IO_PMC.UART.FCR.bit.FE1 == 0 )) || 
		   (( IO_PMC.UART.FCR.bit.FSEL == 1 ) && ( IO_PMC.UART.FCR.bit.FE2 == 0 )) ){
			 IO_PMC.UART.FCR.bit.FSEL = 0;
			 IO_PMC.UART.FCR.bit.FE1 = 1;
			 dd_pmc_uart_dsb();
		}

		// SpinLock.
		Dd_ARM_Critical_Section_Start();
		
		// Set DMA data.
		src_addr = (ULONG)(gDD_PMC_Uart_Mng.send_buff_addr + gDD_PMC_Uart_Buff_Info.s_read_pos);
		dst_addr = (ULONG)(&(IO_PMC.UART.DR));
		if( (gDD_PMC_Uart_Buff_Info.s_write_pos <= gDD_PMC_Uart_Buff_Info.s_read_pos) && (gDD_PMC_Uart_Buff_Info.s_flag == 1) ) {
			send_size = gDD_PMC_Uart_Mng.send_buff_size - gDD_PMC_Uart_Buff_Info.s_read_pos;
		}
		else {
			send_size = gDD_PMC_Uart_Buff_Info.s_size;
		}

//		DDIM_User_L1l2cache_Clean_Flush_Addr( src_addr, send_size );
		
		// SpinUnLock.
		Dd_ARM_Critical_Section_End();
		
		// Start DMA
		ret = dd_pmc_uart_dma_copy( dma_ch, src_addr, dst_addr, send_size );
		
		if( ret == D_DDIM_OK ){
			// Start DMA by UART FIFO interrupt.
			IO_PMC.UART.FCR.bit.FTIE = 1;
			dd_pmc_uart_dsb();
			
			// SpinLock.
			Dd_ARM_Critical_Section_Start();
			
			// Increment read position.
			gDD_PMC_Uart_Buff_Info.s_read_pos += send_size;
			gDD_PMC_Uart_Buff_Info.s_size -= send_size;
			
			if( gDD_PMC_Uart_Buff_Info.s_read_pos >= gDD_PMC_Uart_Mng.send_buff_size ){
				gDD_PMC_Uart_Buff_Info.s_read_pos -= gDD_PMC_Uart_Mng.send_buff_size;
				gDD_PMC_Uart_Buff_Info.s_flag--;		// The flag is dropped
			}
			
			// SpinUnLock.
			Dd_ARM_Critical_Section_End();
		}
		else{
			// DMA Start NG
			Ddim_Print(("dd_pmc_uart_dma_copy() error. ret=0x%x\n", ret));
			
			// End DMA transfer process.
			IO_PMC.UART.FCR.bit.FTIE = 0;
			dd_pmc_uart_dsb();
			
			while( IO_PMC.UART.SSR.bit.__TBI == 0 ){
				DDIM_User_Dly_Tsk(1);		// wait until TDR empty
				ret2 = dd_pmc_uart_check_stopping_conditions();
				if( ret2 != D_DDIM_OK ){
					return ret2;
				}
			}
			if( gDD_PMC_Uart_Info.force_stop_flg == 1 ){
				gDD_PMC_Uart_Info.force_stop_flg = 0;
				return D_DD_PMC_UART_FORCE_STOP;
			}
		}
	}
	return ret;
}
#endif
